home *** CD-ROM | disk | FTP | other *** search
/ Mac Easy 2010 May / Mac Life Ubuntu.iso / casper / filesystem.squashfs / usr / src / linux-headers-2.6.28-15 / arch / sparc / include / asm / spinlock_64.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-12-24  |  5.2 KB  |  249 lines

  1. /* spinlock.h: 64-bit Sparc spinlock support.
  2.  *
  3.  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  4.  */
  5.  
  6. #ifndef __SPARC64_SPINLOCK_H
  7. #define __SPARC64_SPINLOCK_H
  8.  
  9. #ifndef __ASSEMBLY__
  10.  
  11. /* To get debugging spinlocks which detect and catch
  12.  * deadlock situations, set CONFIG_DEBUG_SPINLOCK
  13.  * and rebuild your kernel.
  14.  */
  15.  
  16. /* All of these locking primitives are expected to work properly
  17.  * even in an RMO memory model, which currently is what the kernel
  18.  * runs in.
  19.  *
  20.  * There is another issue.  Because we play games to save cycles
  21.  * in the non-contention case, we need to be extra careful about
  22.  * branch targets into the "spinning" code.  They live in their
  23.  * own section, but the newer V9 branches have a shorter range
  24.  * than the traditional 32-bit sparc branch variants.  The rule
  25.  * is that the branches that go into and out of the spinner sections
  26.  * must be pre-V9 branches.
  27.  */
  28.  
  29. #define __raw_spin_is_locked(lp)    ((lp)->lock != 0)
  30.  
  31. #define __raw_spin_unlock_wait(lp)    \
  32.     do {    rmb();            \
  33.     } while((lp)->lock)
  34.  
  35. static inline void __raw_spin_lock(raw_spinlock_t *lock)
  36. {
  37.     unsigned long tmp;
  38.  
  39.     __asm__ __volatile__(
  40. "1:    ldstub        [%1], %0\n"
  41. "    membar        #StoreLoad | #StoreStore\n"
  42. "    brnz,pn        %0, 2f\n"
  43. "     nop\n"
  44. "    .subsection    2\n"
  45. "2:    ldub        [%1], %0\n"
  46. "    membar        #LoadLoad\n"
  47. "    brnz,pt        %0, 2b\n"
  48. "     nop\n"
  49. "    ba,a,pt        %%xcc, 1b\n"
  50. "    .previous"
  51.     : "=&r" (tmp)
  52.     : "r" (lock)
  53.     : "memory");
  54. }
  55.  
  56. static inline int __raw_spin_trylock(raw_spinlock_t *lock)
  57. {
  58.     unsigned long result;
  59.  
  60.     __asm__ __volatile__(
  61. "    ldstub        [%1], %0\n"
  62. "    membar        #StoreLoad | #StoreStore"
  63.     : "=r" (result)
  64.     : "r" (lock)
  65.     : "memory");
  66.  
  67.     return (result == 0UL);
  68. }
  69.  
  70. static inline void __raw_spin_unlock(raw_spinlock_t *lock)
  71. {
  72.     __asm__ __volatile__(
  73. "    membar        #StoreStore | #LoadStore\n"
  74. "    stb        %%g0, [%0]"
  75.     : /* No outputs */
  76.     : "r" (lock)
  77.     : "memory");
  78. }
  79.  
  80. static inline void __raw_spin_lock_flags(raw_spinlock_t *lock, unsigned long flags)
  81. {
  82.     unsigned long tmp1, tmp2;
  83.  
  84.     __asm__ __volatile__(
  85. "1:    ldstub        [%2], %0\n"
  86. "    membar        #StoreLoad | #StoreStore\n"
  87. "    brnz,pn        %0, 2f\n"
  88. "     nop\n"
  89. "    .subsection    2\n"
  90. "2:    rdpr        %%pil, %1\n"
  91. "    wrpr        %3, %%pil\n"
  92. "3:    ldub        [%2], %0\n"
  93. "    membar        #LoadLoad\n"
  94. "    brnz,pt        %0, 3b\n"
  95. "     nop\n"
  96. "    ba,pt        %%xcc, 1b\n"
  97. "     wrpr        %1, %%pil\n"
  98. "    .previous"
  99.     : "=&r" (tmp1), "=&r" (tmp2)
  100.     : "r"(lock), "r"(flags)
  101.     : "memory");
  102. }
  103.  
  104. /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
  105.  
  106. static void inline __read_lock(raw_rwlock_t *lock)
  107. {
  108.     unsigned long tmp1, tmp2;
  109.  
  110.     __asm__ __volatile__ (
  111. "1:    ldsw        [%2], %0\n"
  112. "    brlz,pn        %0, 2f\n"
  113. "4:     add        %0, 1, %1\n"
  114. "    cas        [%2], %0, %1\n"
  115. "    cmp        %0, %1\n"
  116. "    membar        #StoreLoad | #StoreStore\n"
  117. "    bne,pn        %%icc, 1b\n"
  118. "     nop\n"
  119. "    .subsection    2\n"
  120. "2:    ldsw        [%2], %0\n"
  121. "    membar        #LoadLoad\n"
  122. "    brlz,pt        %0, 2b\n"
  123. "     nop\n"
  124. "    ba,a,pt        %%xcc, 4b\n"
  125. "    .previous"
  126.     : "=&r" (tmp1), "=&r" (tmp2)
  127.     : "r" (lock)
  128.     : "memory");
  129. }
  130.  
  131. static int inline __read_trylock(raw_rwlock_t *lock)
  132. {
  133.     int tmp1, tmp2;
  134.  
  135.     __asm__ __volatile__ (
  136. "1:    ldsw        [%2], %0\n"
  137. "    brlz,a,pn    %0, 2f\n"
  138. "     mov        0, %0\n"
  139. "    add        %0, 1, %1\n"
  140. "    cas        [%2], %0, %1\n"
  141. "    cmp        %0, %1\n"
  142. "    membar        #StoreLoad | #StoreStore\n"
  143. "    bne,pn        %%icc, 1b\n"
  144. "     mov        1, %0\n"
  145. "2:"
  146.     : "=&r" (tmp1), "=&r" (tmp2)
  147.     : "r" (lock)
  148.     : "memory");
  149.  
  150.     return tmp1;
  151. }
  152.  
  153. static void inline __read_unlock(raw_rwlock_t *lock)
  154. {
  155.     unsigned long tmp1, tmp2;
  156.  
  157.     __asm__ __volatile__(
  158. "    membar    #StoreLoad | #LoadLoad\n"
  159. "1:    lduw    [%2], %0\n"
  160. "    sub    %0, 1, %1\n"
  161. "    cas    [%2], %0, %1\n"
  162. "    cmp    %0, %1\n"
  163. "    bne,pn    %%xcc, 1b\n"
  164. "     nop"
  165.     : "=&r" (tmp1), "=&r" (tmp2)
  166.     : "r" (lock)
  167.     : "memory");
  168. }
  169.  
  170. static void inline __write_lock(raw_rwlock_t *lock)
  171. {
  172.     unsigned long mask, tmp1, tmp2;
  173.  
  174.     mask = 0x80000000UL;
  175.  
  176.     __asm__ __volatile__(
  177. "1:    lduw        [%2], %0\n"
  178. "    brnz,pn        %0, 2f\n"
  179. "4:     or        %0, %3, %1\n"
  180. "    cas        [%2], %0, %1\n"
  181. "    cmp        %0, %1\n"
  182. "    membar        #StoreLoad | #StoreStore\n"
  183. "    bne,pn        %%icc, 1b\n"
  184. "     nop\n"
  185. "    .subsection    2\n"
  186. "2:    lduw        [%2], %0\n"
  187. "    membar        #LoadLoad\n"
  188. "    brnz,pt        %0, 2b\n"
  189. "     nop\n"
  190. "    ba,a,pt        %%xcc, 4b\n"
  191. "    .previous"
  192.     : "=&r" (tmp1), "=&r" (tmp2)
  193.     : "r" (lock), "r" (mask)
  194.     : "memory");
  195. }
  196.  
  197. static void inline __write_unlock(raw_rwlock_t *lock)
  198. {
  199.     __asm__ __volatile__(
  200. "    membar        #LoadStore | #StoreStore\n"
  201. "    stw        %%g0, [%0]"
  202.     : /* no outputs */
  203.     : "r" (lock)
  204.     : "memory");
  205. }
  206.  
  207. static int inline __write_trylock(raw_rwlock_t *lock)
  208. {
  209.     unsigned long mask, tmp1, tmp2, result;
  210.  
  211.     mask = 0x80000000UL;
  212.  
  213.     __asm__ __volatile__(
  214. "    mov        0, %2\n"
  215. "1:    lduw        [%3], %0\n"
  216. "    brnz,pn        %0, 2f\n"
  217. "     or        %0, %4, %1\n"
  218. "    cas        [%3], %0, %1\n"
  219. "    cmp        %0, %1\n"
  220. "    membar        #StoreLoad | #StoreStore\n"
  221. "    bne,pn        %%icc, 1b\n"
  222. "     nop\n"
  223. "    mov        1, %2\n"
  224. "2:"
  225.     : "=&r" (tmp1), "=&r" (tmp2), "=&r" (result)
  226.     : "r" (lock), "r" (mask)
  227.     : "memory");
  228.  
  229.     return result;
  230. }
  231.  
  232. #define __raw_read_lock(p)    __read_lock(p)
  233. #define __raw_read_trylock(p)    __read_trylock(p)
  234. #define __raw_read_unlock(p)    __read_unlock(p)
  235. #define __raw_write_lock(p)    __write_lock(p)
  236. #define __raw_write_unlock(p)    __write_unlock(p)
  237. #define __raw_write_trylock(p)    __write_trylock(p)
  238.  
  239. #define __raw_read_can_lock(rw)        (!((rw)->lock & 0x80000000UL))
  240. #define __raw_write_can_lock(rw)    (!(rw)->lock)
  241.  
  242. #define _raw_spin_relax(lock)    cpu_relax()
  243. #define _raw_read_relax(lock)    cpu_relax()
  244. #define _raw_write_relax(lock)    cpu_relax()
  245.  
  246. #endif /* !(__ASSEMBLY__) */
  247.  
  248. #endif /* !(__SPARC64_SPINLOCK_H) */
  249.